<?php

namespace App\Http\Controllers\Admin\Conf;

use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Conf\SettingRequest;
use App\Models\Admin\Conf\Setting;
use App\Models\Admin\Conf\SettingOption;
use App\Repositories\Admin\Conf\SettingRepository;
use Encore\Admin\Controllers\ModelForm;
use Encore\Admin\Facades\Admin;
use Encore\Admin\Form;
use Encore\Admin\Grid;
use Encore\Admin\Layout\Content;
use Flash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Route;
use Response;
use DB;
use Exception;

class SettingController extends Controller
{
    use ModelForm;

    /** @var  SettingRepository */
    private $settingRepository;

    public function __construct(SettingRepository $settingRepo)
    {
        $this->settingRepository = $settingRepo;
    }

    /**
     * Display a listing of the Setting.
     *
     * @return Response
     */
    public function index()
    {
        // return Admin::content(function (Content $content) {

        //     $content->header(__('admin.conf.settings.index_header'));
        //     $content->description(__('admin.conf.settings.index_description'));

        //     $content->body($this->grid());
        // });

        // 只能手动调用下函数
        Admin::script('adminConfSetting();');
        $settings = SettingOption::with(['setting'])->get();
        return view('admin.conf.setting.index')->with('settings', $settings);
    }

    /**
     * Show the form for creating a new Setting.
     *
     * @return Response
     */
    public function create()
    {
        return Admin::content(function (Content $content) {

            $content->header(__('admin.conf.settings.create_header'));
            $content->description(__('admin.conf.settings.create_description'));

            $content->body($this->form());

        });
    }

    /**
     * Store a newly created Setting in storage.
     *
     * @param SettingRequest $request
     *
     * @return Response
     */
    public function store(SettingRequest $request)
    {
        // 获得所有选项的name和id
        $settingOptions = SettingOption::pluck('id', 'name');
        // dd($settingOptions->keys()->toArray());
        // 获得所有选项的name
        $input = $request->only($settingOptions->keys()->toArray());
        $datas = [];
        foreach ($settingOptions as $key => $value) {
            $data = [];
            $data['value'] = '';
            $data['setting_option_id'] = $value;
            $data['created_at'] = date('Y-m-d H:i:s', time());
            $data['created_at'] = date('Y-m-d H:i:s', time());
            if (isset($input[$key])) {
                $data['value'] = $input[$key];
            }
            $datas[] = $data;
        }

        // 开启事务, 批量插入
        DB::beginTransaction();
        try {
            // 先清空配置表
            DB::table('settings')->delete();
            // 再写入配置表
            if (!empty($datas)) {
                DB::table('settings')->insert($datas);
            }
            DB::commit();
        } catch (\Exception $e) {
            DB::rollback(); //事务回滚
            echo $e->getMessage();
            dd($e->getCode());
        }

        // $setting = $this->settingRepository->create($input);

        Flash::success(__('admin.conf.settings.saved_success'));

        return Input::get('_previous_') ? redirect(Input::get('_previous_')) : redirect(route('admin.conf.settings.index'));

    }

    /**
     * Display the specified Setting.
     *
     * @param  int $id
     *
     * @return Response
     */
    public function show($id)
    {
        $setting = $this->settingRepository->findWithoutFail($id);

        if (empty($setting)) {
            Flash::error(__('admin.conf.settings.not_found'));

            return redirect(route('admin.conf.settings.index'));
        }

        return view('admin.conf.settings.show')->with('setting', $setting);

    }

    /**
     * Show the form for editing the specified Setting.
     *
     * @param  int $id
     *
     * @return Response
     */
    public function edit($id)
    {
        return Admin::content(function (Content $content) use ($id) {

            $content->header(__('admin.conf.settings.edit_header'));
            $content->description(__('admin.conf.settings.edit_description'));

            $content->body($this->form()->edit($id));
        });
    }

    /**
     * Update the specified Setting in storage.
     *
     * @param  int              $id
     * @param SettingRequest $request
     *
     * @return Response
     */
    public function update($id, SettingRequest $request)
    {
        $setting = $this->settingRepository->findWithoutFail($id);

        if (empty($setting)) {
            Flash::error(__('admin.conf.settings.not_found'));

            return redirect(route('admin.conf.settings.index'));
        }

        $setting = $this->settingRepository->update($request->all(), $id);
        


        Flash::success(__('admin.conf.settings.updated_success'));

        return Input::get('_previous_') ? redirect(Input::get('_previous_')) : redirect(route('admin.conf.settings.index'));
    }

    /**
     * Remove the specified Setting from storage.
     *
     * @param  int $id
     *
     * @return Response
     */
    public function destroy($id)
    {
        // 根据 `,` 判断传递过来的是单个id还是多个id
        if (substr_count($id, ',') >= 1) {
            $id = explode(",", $id);
        }

        // 如果是数组则进行批量删除
        if (is_array($id)) {
            if ($flag = $this->settingRepository->batchDelete('id', $id)) {
                return response()->json(['message' => __('admin.conf.settings.deleted_success'), 'status' => $flag]);
            } else {
                return response()->json(['message' => __('base.deleted.error'), 'status' => $flag]);
            }
        }

        $setting = $this->settingRepository->findWithoutFail($id);

        if (empty($setting)) {
            Flash::error(__('admin.conf.settings.not_found'));

            return redirect(route('admin.conf.settings.index'));
        }

        if ($flag = $this->settingRepository->delete($id)) {
        
            return response()->json(['message' => __('admin.conf.settings.deleted_success'), 'status' => $flag]);
        } else {
            return response()->json(['message' => __('base.deleted.error'), 'status' => $flag]);
        }
    }

    /**
     * [writeConfig 将配置项写到配置文件中]
     * @return [type] [description]
     */
    public function writeConfig()
    {
        $path = config_path() . '/' . 'custom/config.php';
        $tempSettings = SettingOption::with(['setting'])->get();
        $settings = [];
        foreach ($tempSettings as $setting) {
            if ($setting->setting) {
                $settings[$setting->name] = $setting->setting->value;
            } else {
                $settings[$setting->name] = '';
            }
        }
        $result = '<?php';
        $result .= PHP_EOL;
        $result .= 'return ';
        $result .= var_export($settings, TRUE);
        $result .= ';';
        if ($flag = file_put_contents($path, $result)) {
            return response()->json(['status' => true, 'content' => '生成配置文件成功!']);
        } else {
            return response()->json(['status' => false, 'content' => '生成配置文件失败!']);
        }

        /**
         * 生成配置项
         */
        // $writeConfig = new Axdlee\Config\Rewrite;
        // dd($this->toFile($path, $settings));
        // $writeConfig->toFile('D:/soft/xampp/htdocs/handong/config/custom/config.php', [
        //     'item' => 'new value',
        //        'int' => 10,
        //        'boolean' => true,
        //        'float' => 5.3,
        //     'arrayItem' => ['Single', 'Level', 'Array', 'Values'],
        //     'numberItem' => 3,
        //     'booleanItem' => true
        // ]);
    }

    public function toFile($filePath, $newValues, $useValidation = true)
    {
        $contents = file_get_contents($filePath);
        $contents = $this->toContent($contents, $newValues, $useValidation);
        file_put_contents($filePath, $contents);
        return $contents;
    }

    public function toContent($contents, $newValues, $useValidation = true)
    {
        $contents = $this->parseContent($contents, $newValues);

        if (!$useValidation) {
            return $contents;
        }

        $result = eval('?>'.$contents);

        // foreach ($newValues as $key => $expectedValue) {
        //     $parts = explode('.', $key);

        //     $array = $result;
        //     foreach ($parts as $part) {
        //         if (!is_array($array) || !array_key_exists($part, $array)) {
        //             throw new Exception(sprintf('Unable to rewrite key "%s" in config, does it exist?', $key));
        //         }

        //         $array = $array[$part];
        //     }
        //     $actualValue = $array;

        //     if ($actualValue != $expectedValue) {
        //         throw new Exception(sprintf('Unable to rewrite key "%s" in config, rewrite failed', $key));
        //     }
        // }

        return $contents;
    }

    protected function parseContent($contents, $newValues)
    {
        $result = $contents;

        foreach ($newValues as $path => $value) {
            $result = $this->parseContentValue($result, $path, $value);
        }

        return $result;
    }

    protected function parseContentValue($contents, $path, $value)
    {
        $result = $contents;
        $items = explode('.', $path);
        $key = array_pop($items);
        $replaceValue = $this->writeValueToPhp($value);

        $count = 0;
        $patterns = array();
        $patterns[] = $this->buildStringExpression($key, $items);
        $patterns[] = $this->buildStringExpression($key, $items, '"');
        $patterns[] = $this->buildConstantExpression($key, $items);
        $patterns[] = $this->buildArrayExpression($key, $items);

        foreach ($patterns as $pattern) {
            if (is_array($value)) {
                $result = preg_replace($pattern, '${1}${2}'.$this->array2str($value), $result, 1, $count);
            } else {
                $result = preg_replace($pattern, '${1}${2}'.$replaceValue, $result, 1, $count);
            }

            if ($count > 0) {
                break;
            }
        }

        if ($count == 0) {
            if (is_array($value)) {
                $result = preg_replace('/(\s*)]\;/', "\n\n\t'{$key}' => ".$this->array2str($value).',${0}', $result, 1, $count);
            } else {
                $result = preg_replace('/(\s*)]\;/', "\n\n\t'{$key}' => ".$replaceValue.',${0}', $result, 1, $count);
            }
        }

        return $result;
    }

    protected function array2str ($data)
    {
        $str = '';
        foreach ($data as $k => $v) {
            if (is_array($v)) {
                $v = self::array2str($v);
                $str .= "\n\t\t'" . $k . "'" . ' => ' .  $v . ",";
            } else {
                $str .= "\n\t\t'" . $k . "'" . ' => ' . "'" . $v . "',";
            }

        }
        return "[".$str."\n\t]";
    }
    protected function writeValueToPhp($value)
    {
        if (is_string($value) && strpos($value, "'") === false) {
            $replaceValue = "'".$value."'";
        }
        elseif (is_string($value) && strpos($value, '"') === false) {
            $replaceValue = '"'.$value.'"';
        }
        elseif (is_bool($value)) {
            $replaceValue = ($value ? 'true' : 'false');
        }
        elseif (is_null($value)) {
            $replaceValue = 'null';
        }
        elseif (is_array($value) && count($value) === count($value, COUNT_RECURSIVE)) {
            $replaceValue = $this->writeArrayToPhp($value);
        }
        else {
            $replaceValue = $value;
        }

        $replaceValue = str_replace('$', '\$', $replaceValue);
        return $replaceValue;
    }

    protected function writeArrayToPhp($array)
    {
        $result = [];

        foreach ($array as $value) {
            if (!is_array($value)) {
                $result[] = $this->writeValueToPhp($value);
            }
        }

        return '['.implode(', ', $result).']';

        return $result;
    }

    protected function buildStringExpression($targetKey, $arrayItems = array(), $quoteChar = "'")
    {
        $expression = array();

        // Opening expression for array items ($1)
        $expression[] = $this->buildArrayOpeningExpression($arrayItems);

        // The target key opening
        $expression[] = '([\'|"]'.$targetKey.'[\'|"]\s*=>\s*)['.$quoteChar.']';

        // The target value to be replaced ($2)
        $expression[] = '([^'.$quoteChar.']*)';

        // The target key closure
        $expression[] = '['.$quoteChar.']';

        return '/' . implode('', $expression) . '/';
    }


    /**
     * Common constants only (true, false, null, integers)
     * @param $targetKey
     * @param array $arrayItems
     * @return string
     */
    protected function buildConstantExpression($targetKey, $arrayItems = array())
    {
        $expression = array();

        // Opening expression for array items ($1)
        $expression[] = $this->buildArrayOpeningExpression($arrayItems);

        // The target key opening ($2)
        $expression[] = '([\'|"]'.$targetKey.'[\'|"]\s*=>\s*)';

        // The target value to be replaced ($3)
        $expression[] = '([tT][rR][uU][eE]|[fF][aA][lL][sS][eE]|[nN][uU][lL]{2}|[\d]+)';

        return '/' . implode('', $expression) . '/';
    }

    /**
     * Single level arrays only
     * @param $targetKey
     * @param array $arrayItems
     * @return string
     */
    protected function buildArrayExpression($targetKey, $arrayItems = array())
    {
        $expression = array();

        // Opening expression for array items ($1)
        $expression[] = $this->buildArrayOpeningExpression($arrayItems);

        // The target key opening ($2)
        $expression[] = '([\'|"]'.$targetKey.'[\'|"]\s*=>\s*)';

        // The target value to be replaced ($3)
        $expression[] = '(?:[aA][rR]{2}[aA][yY]\(|[\[])([^\]|)]*)[\]|)]';

        return '/' . implode('', $expression) . '/';
    }

    protected function buildArrayOpeningExpression($arrayItems)
    {
        if (count($arrayItems)) {
            $itemOpen = array();
            foreach ($arrayItems as $item) {
                // The left hand array assignment
                $itemOpen[] = '[\'|"]'.$item.'[\'|"]\s*=>\s*(?:[aA][rR]{2}[aA][yY]\(|[\[])';
            }

            // Capture all opening array (non greedy)
            $result = '(' . implode('[\s\S]*', $itemOpen) . '[\s\S]*?)';
        }
        else {
            // Gotta capture something for $1
            $result = '()';
        }

        return $result;
    }

    /**
     * [form description]
     * @return {[type]} [description]
     */
    protected function form()
    {
        return Admin::form(Setting::class, function (Form $form) {

            $form->display('id', 'ID');
            $form->text('name', '配置项名称');
            $form->text('value', '值');

            $form->display('created_at', __('base.created_at'));
            $form->display('updated_at', __('base.updated_at'));

        });
    }

    /**
     * [grid description]
     * @return {[type]} [description]
     */
    protected function grid()
    {

        return Admin::grid(Setting::class, function (Grid $grid) {
            // 考虑是否需要scope和排序
            // $grid->model()->orderBy('listorder', 'asc');

            // //添加按钮
            // if (!\Gate::check('admin.conf.settings.create')) {
            //     $grid->disableCreation();
            // }

            // // 编辑和删除按钮
            // $grid->actions(function ($actions) {
            //     //编辑按钮
            //     if (!\Gate::check('admin.conf.settings.edit')) {
            //         $actions->disableEdit();
            //     }
            //     //删除按钮
            //     if (!\Gate::check('admin.conf.settings.destroy')) {
            //         $actions->disableDelete();
            //     }
            // });

            // //导出按钮
            // if (!\Gate::check('admin.conf.settings.export')) {
            //     $grid->disableExport();
            // }

            // //批量操作
            // $grid->tools(function ($tools) {
            //     $tools->batch(function ($batch) {
            //         //批量删除按钮
            //         if (!\Gate::check('admin.conf.settings.batch_destroy')) {
            //             $batch->disableDelete();
            //         }
            //     });
            // });

            //添加按钮
            if (Admin::user()->cannot('admin.conf.settings.create')) {
                $grid->disableCreation();
            }

            // 编辑和删除按钮
            $grid->actions(function ($actions) {
                //编辑按钮
                if (Admin::user()->cannot('admin.conf.settings.edit')) {
                    $actions->disableEdit();
                }
                //删除按钮
                if (Admin::user()->cannot('admin.conf.settings.destroy')) {
                    $actions->disableDelete();
                }
            });

            //导出按钮
            if (Admin::user()->cannot('admin.conf.settings.export')) {
                $grid->disableExport();
            }

            //批量操作
            $grid->tools(function ($tools) {
                $tools->batch(function ($batch) {
                    //批量删除按钮
                    if (Admin::user()->cannot('admin.conf.settings.batch_destroy')) {
                        $batch->disableDelete();
                    }
                });
            });

            $grid->column('name', '配置项名称')->sortable();
            $grid->column('value', '默认值')->sortable();

            
            /**
             * 过滤处理
             */
            // $grid->filter(function ($filter) {
                // // 禁用id查询框
                // $filter->disableIdFilter();
                // // 名称
                // $filter->like('name', '内容模板类型名称');
                // // 模板别名
                // $filter->like('alias', '模板类型别名');
            // });
        });
    }
}
